По ходу решаемых задач, мне необходимо мониторить не только физические машины стандартыми средствами zabbix но и ловить snmp trap-ы от спецефических программ работающих на этих машинах. Пересмотрев несколько вариантов настройки на wiki и форумах , я понял что существующие решения не удовлетворяют мои нужды. Поэтому решил написать свой обработчик snmp traps, взяв за основу один из тех что был на форуме.
Если вам интересно - читаете дальше.
Что он может:
• Делаются запросы в базу zabbix, для того чтобы найти нужный hostname по IP адресу, или нужный IP по hostname
• Файл exclude, содержащий строчки с регулярными выражениями, которые применяются к комбинированному значению трапа, и при совпадении – трап не передается в zabbix. Применяю для удаления «ненужных» трапов типа Heartbeat и т.д.
• Файл aliases, содержащий значения типа IP – hostname. Применяется в случае когда трапы приходят с разных IP при нескольких NIC, или когда трапы приходят с нескольких физических устройств, а «логично» было бы их хранить в одном месте.
• И, самое интересное, делается запрос в базу zabbix для того чтобы найти нужный item для которого пришел данный трап (при получении трапа скрипт находит ключевое значение которое передается как значение SNMPv2-MIB::snmpTrapOID.0). Причем выборка делается по key, и в zabbix можно создавать несколько item для разных трапов, и key может быть «общим» для нескольких трапов. Пример: если в zabbix есть хост TrapTest, и для него созданны item (типа Zabbix Trapper) с значением key = .1.3.6.1, и второй item с значением key = .1.3.6.1.4.1, то при получение трапа который раскодируется в .1.3.6.1.4.1.5.6 он сядет во второй item, а при получение трапа которой раскодируется в .1.3.6.1.4 то он сядет в первый item.
Минусы данного решения:
• для каждого прнятого трапа делается 2 запроса в базу zabbix, что, при наличии довольно большого количества машин и принимаемых трапов может увеличить нагрузку на базу. (Хотя правильное использование exclude файла помогает разрузить zabbix от ненужных трапов)
• для каждого принятого трапа запускается отдельный процесс обработчик, что также может повлиять на нагрузку машины (но это уже скорее проблема не моего решения, а реализации обработчика трапов от net-snmp, и для решения этой проблемы надо чтобы разработчики zabbix включили в всой продукт свою реализацию стаднартного процесса net-snmp snmptrapd
Как настраивать:
Попробую показать инструкцию как с этим всем работать на примере CentOS 5.4 и версии zabbix 1.8 и net-snmp-5.3.2.2-7.el5
Установите perl скрипт в любую директорию (я использую /usr/local/sbin/), предварительно раскрыв из архива.
Для запуска вам необходимо иметь на машине следующие perl модули: DBI и DBD::Mysql.
Они для моей системы доступны в RPM пакетах perl-DBI-1.52-2.el5 иperl-DBD-MySQL-3.0007-2.el5
Отредактируйте скрипт под ваши нужды:
• Для начала рекомендую включить режим отладки
my $DEBUG = 1;
• Все будет записываться в следующий файл
my $DEBUGFILE = "/tmp/zabbix_snmptrapdebug_new.log";
• Адрес zabbix сервера, и порт
my $ZABBIX_SERVER = "";
my $ZABBIX_PORT = 10051;
• Имя хоста по умолчанию куда будут отправляться трапы если у zabbix не будет создан хост для которого приходят трапы
my $WILDCARD_HOST = "TRAP_HOST
• Если 1 то не пытаться найти хост по базе а отправлять все на хост по умолчанию (не знаю какой смысл вам это использовать
my $SEND_ALL_TO_WILDCARD = 0
• Имя Item по умолчанию куда будут отправляться трапы для хостов. Обязательно должно совпадать с тем что вы создаете в zabbix
my $ZABBIX_ITEM = "snmptraps";
• Путь к zabbix_sender
my $ZABBIX_SENDER = "/usr/local/bin/zabbix_sender";
• Адрес базы zabbix, username и password
my $ZABBIX_DB_HOST="";
my $ZABBIX_DB_NAME="zabbix";
my $ZABBIX_DB_USER="zabbix";
my $ZABBIX_DB_PASS=" ";
• Путь и имя файла в котором перечисленны регулярные выражения (несколько строк) которые применяются к полученному трапу, и в случае совпадения, этот трап не отсылается в zabbix. Применяется для «отсева» не нужных трапов.
my $TRAPEXCLUDEFILE="/usr/local/sbin/traps_to_exclude";
• Имя файла содержащего строчки из двух полей разделенных табулятором типа IP<TAB>hostname. Если у нас трапы приходят от другого адреса чем у нас создан хост на zabbix (в случае нескольких сетевых адаптеров)
my $ALIASFILE="/usr/local/sbin/aliasfile";
• По умолчание snmptrapd передает трапы в виде SNMP-COMMUNITY-MIB::snmpTrapAddress.0. Этот параметр позволяет отрезать «лишнее» до «::»для уменьшение общего размера данных и приводит к виду snmpTrapAddress.0
my $TRIMLONGVALUES=1;
На той машине куда пересылаются от устройств все трапы надо правильно их настроить на прием. Для этого там должен быть запущен snmptrapd из пакета net-snmp. Как минимум в кофигурационном файле должно быть указанно:
# cat /etc/snmp/snmptrapd.conf
disableAuthorization yes
traphandle default /usr/local/sbin/zabbix_snmptraphandler.pl
Где в строчке traphandle указан полный путь нашего скрипта обработчика.
И естественно скрипт должен иметь права на исполнение.
Дальше нам понадобится файл описания SNMP от устройства – MIB file. Который содержит фактически описание что и как будет приниматься по SNMP. Дело в том что устройства посылают всю информацию (oid) в виде .1.3.6.1 и т.д., что не читабельно и не понятно. И как раз в MIB файле и содержится описание, что конкретно значит данный oid.
Для стандартных устройств MIB файлы можно найти в интернете, а для ваших специфических – надо уточнять у поставщика оборудования или искать в интернете (очень неплохой ресурс - http://www.oidview.com/mibs/detail.html).
По умолчанию (по крайней мере у меня так) файлы в системе хранятся в /usr/share/snmp/mibs
Скопируйте ваш файл в эту директорию.
Отредактируйте файл /etc/snmp/snmp.conf и добавьте туда строчку типа
mibs +ИМЯ_МИБ_МОДУЛЯ
Для того чтоб найти ИМЯ_МИБ_МОДУЛЯ, откройте MIB файл и найдите строчку типа NET-SNMP-MIB DEFINITIONS ::= BEGIN
То что слева до DEFINITIONS, это и есть нужное имя.
(Я делаю так – и это работает. Наверняка можно и по другому. Смотрите man snmp.conf)
Перезапустите snmptrapd сервис:
#service snmptrad restart
Теперь net-snmp готов принимать трапы для вашего оборудования.
Далее настраиваем zabbix.
Создаем host с именем как указано в нашем скрипте (zabbix_snmptraphandler.pl) $WILDCARD_HOST. Он используется если пришел трап от утройства которое не добавленно еще в zabbix. Добавляем к этому хосту item типа zabbix trapper и типом получаемой информации Text, c Key как указанно в нашем скрипте переменной $ZABBIX_ITEM. Это имя по умолчание куда будут оправляться наши трапы если не было созданно для них персональных items.
Теперь создаем хосты для нашего оборудования, и добавляем для них также item типа zabbix trapper и типом получаемой информации Text, c Key как указанно в нашем скрипте переменной $ZABBIX_ITEM.
Если мы знаем заранее список тех трапов которые могут приходить от конкретного оборудования, создаем также персональные item-ы типа zabbix trapper но в Key указываем цифровое предсавление трапа. Для получение такого представления в коммандной строке выполняем команду с указанием того трапа который мы ожидаем:
# snmptranslate -On CPQHLTH-MIB::cpqHe4FltTolPowerSupplyOk
В ответ получаем строчку типа .1.3.6.1.4.1.232.0.6048
Это и есть цифровое представление.
Теперь если мы в Key создаваемого Item укажем .1.3.6.1.4.1.232.0.6048 то все трапы данного типа будет отправленны на этот итем. Если же мы укажем Key типа .1.3.6.1.4.1.232.0 то также все другие трапы которые попадают под это дело (со списком можно ознакомится с помощью команды snmptranslate -Tp .1.3.6.1.4.1.232.0) будут отправлены этому Item-у. Таким образом мы можем создавать «общие» для каждого типа трапов Items.
Для того чтобы наш новый итем правильно работал с тригерами делаем следующее, на один итем настраиваем столько забикс тригеров, сколько у нас реальных SNMP трапов возможно посылает данный тип оборудования (набо смотреть MIB файл). Для каждого тригера ставим выражение типа:
Где хххх это тот итем что мы создали, в первой функции str() надо указать тот уникальный текст который присутствует при получении данного трапа, а в второй функции str() надо указать тот уникальный текст который присутствует при исправлении предыдущей ошибки трапа.
В таком случае тригер будет правильно отрабатывать все события, и не надо никакого nodata()
Для того чтоб не мучаться с большим количеством тригеров, я использую простые скрипты генерации xml файлов для импорта. К сожалению, так как в MIB файлах в описании трапов никто не придерживается стандартов, для каждого MIB файла приходится подправлять скрипт генерации xml, и поэтому выкладывать его нет смысла.
Если вам интересно - читаете дальше.

Что он может:
• Делаются запросы в базу zabbix, для того чтобы найти нужный hostname по IP адресу, или нужный IP по hostname
• Файл exclude, содержащий строчки с регулярными выражениями, которые применяются к комбинированному значению трапа, и при совпадении – трап не передается в zabbix. Применяю для удаления «ненужных» трапов типа Heartbeat и т.д.
• Файл aliases, содержащий значения типа IP – hostname. Применяется в случае когда трапы приходят с разных IP при нескольких NIC, или когда трапы приходят с нескольких физических устройств, а «логично» было бы их хранить в одном месте.
• И, самое интересное, делается запрос в базу zabbix для того чтобы найти нужный item для которого пришел данный трап (при получении трапа скрипт находит ключевое значение которое передается как значение SNMPv2-MIB::snmpTrapOID.0). Причем выборка делается по key, и в zabbix можно создавать несколько item для разных трапов, и key может быть «общим» для нескольких трапов. Пример: если в zabbix есть хост TrapTest, и для него созданны item (типа Zabbix Trapper) с значением key = .1.3.6.1, и второй item с значением key = .1.3.6.1.4.1, то при получение трапа который раскодируется в .1.3.6.1.4.1.5.6 он сядет во второй item, а при получение трапа которой раскодируется в .1.3.6.1.4 то он сядет в первый item.
Минусы данного решения:
• для каждого прнятого трапа делается 2 запроса в базу zabbix, что, при наличии довольно большого количества машин и принимаемых трапов может увеличить нагрузку на базу. (Хотя правильное использование exclude файла помогает разрузить zabbix от ненужных трапов)
• для каждого принятого трапа запускается отдельный процесс обработчик, что также может повлиять на нагрузку машины (но это уже скорее проблема не моего решения, а реализации обработчика трапов от net-snmp, и для решения этой проблемы надо чтобы разработчики zabbix включили в всой продукт свою реализацию стаднартного процесса net-snmp snmptrapd

Как настраивать:
Попробую показать инструкцию как с этим всем работать на примере CentOS 5.4 и версии zabbix 1.8 и net-snmp-5.3.2.2-7.el5
Установите perl скрипт в любую директорию (я использую /usr/local/sbin/), предварительно раскрыв из архива.
Для запуска вам необходимо иметь на машине следующие perl модули: DBI и DBD::Mysql.
Они для моей системы доступны в RPM пакетах perl-DBI-1.52-2.el5 иperl-DBD-MySQL-3.0007-2.el5
Отредактируйте скрипт под ваши нужды:
• Для начала рекомендую включить режим отладки
my $DEBUG = 1;
• Все будет записываться в следующий файл
my $DEBUGFILE = "/tmp/zabbix_snmptrapdebug_new.log";
• Адрес zabbix сервера, и порт
my $ZABBIX_SERVER = "";
my $ZABBIX_PORT = 10051;
• Имя хоста по умолчанию куда будут отправляться трапы если у zabbix не будет создан хост для которого приходят трапы
my $WILDCARD_HOST = "TRAP_HOST
• Если 1 то не пытаться найти хост по базе а отправлять все на хост по умолчанию (не знаю какой смысл вам это использовать

my $SEND_ALL_TO_WILDCARD = 0
• Имя Item по умолчанию куда будут отправляться трапы для хостов. Обязательно должно совпадать с тем что вы создаете в zabbix
my $ZABBIX_ITEM = "snmptraps";
• Путь к zabbix_sender
my $ZABBIX_SENDER = "/usr/local/bin/zabbix_sender";
• Адрес базы zabbix, username и password
my $ZABBIX_DB_HOST="";
my $ZABBIX_DB_NAME="zabbix";
my $ZABBIX_DB_USER="zabbix";
my $ZABBIX_DB_PASS=" ";
• Путь и имя файла в котором перечисленны регулярные выражения (несколько строк) которые применяются к полученному трапу, и в случае совпадения, этот трап не отсылается в zabbix. Применяется для «отсева» не нужных трапов.
my $TRAPEXCLUDEFILE="/usr/local/sbin/traps_to_exclude";
• Имя файла содержащего строчки из двух полей разделенных табулятором типа IP<TAB>hostname. Если у нас трапы приходят от другого адреса чем у нас создан хост на zabbix (в случае нескольких сетевых адаптеров)
my $ALIASFILE="/usr/local/sbin/aliasfile";
• По умолчание snmptrapd передает трапы в виде SNMP-COMMUNITY-MIB::snmpTrapAddress.0. Этот параметр позволяет отрезать «лишнее» до «::»для уменьшение общего размера данных и приводит к виду snmpTrapAddress.0
my $TRIMLONGVALUES=1;
На той машине куда пересылаются от устройств все трапы надо правильно их настроить на прием. Для этого там должен быть запущен snmptrapd из пакета net-snmp. Как минимум в кофигурационном файле должно быть указанно:
# cat /etc/snmp/snmptrapd.conf
disableAuthorization yes
traphandle default /usr/local/sbin/zabbix_snmptraphandler.pl
Где в строчке traphandle указан полный путь нашего скрипта обработчика.
И естественно скрипт должен иметь права на исполнение.
Дальше нам понадобится файл описания SNMP от устройства – MIB file. Который содержит фактически описание что и как будет приниматься по SNMP. Дело в том что устройства посылают всю информацию (oid) в виде .1.3.6.1 и т.д., что не читабельно и не понятно. И как раз в MIB файле и содержится описание, что конкретно значит данный oid.
Для стандартных устройств MIB файлы можно найти в интернете, а для ваших специфических – надо уточнять у поставщика оборудования или искать в интернете (очень неплохой ресурс - http://www.oidview.com/mibs/detail.html).
По умолчанию (по крайней мере у меня так) файлы в системе хранятся в /usr/share/snmp/mibs
Скопируйте ваш файл в эту директорию.
Отредактируйте файл /etc/snmp/snmp.conf и добавьте туда строчку типа
mibs +ИМЯ_МИБ_МОДУЛЯ
Для того чтоб найти ИМЯ_МИБ_МОДУЛЯ, откройте MIB файл и найдите строчку типа NET-SNMP-MIB DEFINITIONS ::= BEGIN
То что слева до DEFINITIONS, это и есть нужное имя.
(Я делаю так – и это работает. Наверняка можно и по другому. Смотрите man snmp.conf)
Перезапустите snmptrapd сервис:
#service snmptrad restart
Теперь net-snmp готов принимать трапы для вашего оборудования.
Далее настраиваем zabbix.
Создаем host с именем как указано в нашем скрипте (zabbix_snmptraphandler.pl) $WILDCARD_HOST. Он используется если пришел трап от утройства которое не добавленно еще в zabbix. Добавляем к этому хосту item типа zabbix trapper и типом получаемой информации Text, c Key как указанно в нашем скрипте переменной $ZABBIX_ITEM. Это имя по умолчание куда будут оправляться наши трапы если не было созданно для них персональных items.
Теперь создаем хосты для нашего оборудования, и добавляем для них также item типа zabbix trapper и типом получаемой информации Text, c Key как указанно в нашем скрипте переменной $ZABBIX_ITEM.
Если мы знаем заранее список тех трапов которые могут приходить от конкретного оборудования, создаем также персональные item-ы типа zabbix trapper но в Key указываем цифровое предсавление трапа. Для получение такого представления в коммандной строке выполняем команду с указанием того трапа который мы ожидаем:
# snmptranslate -On CPQHLTH-MIB::cpqHe4FltTolPowerSupplyOk
В ответ получаем строчку типа .1.3.6.1.4.1.232.0.6048
Это и есть цифровое представление.
Теперь если мы в Key создаваемого Item укажем .1.3.6.1.4.1.232.0.6048 то все трапы данного типа будет отправленны на этот итем. Если же мы укажем Key типа .1.3.6.1.4.1.232.0 то также все другие трапы которые попадают под это дело (со списком можно ознакомится с помощью команды snmptranslate -Tp .1.3.6.1.4.1.232.0) будут отправлены этому Item-у. Таким образом мы можем создавать «общие» для каждого типа трапов Items.
Для того чтобы наш новый итем правильно работал с тригерами делаем следующее, на один итем настраиваем столько забикс тригеров, сколько у нас реальных SNMP трапов возможно посылает данный тип оборудования (набо смотреть MIB файл). Для каждого тригера ставим выражение типа:
Code:
({Template_Test_SNMPTraps:.1.3.6.1.4.1.xxxx.1.str(Raised-alarm_Number_15)}=1 & {TRIGGER.VALUE}=0) | ({Template_Test_SNMPTraps:.1.3.6.1.4.1.xxxx.1.str(Cleared-alarm_Number_15)}#1 & {TRIGGER.VALUE}=1)
В таком случае тригер будет правильно отрабатывать все события, и не надо никакого nodata()

Для того чтоб не мучаться с большим количеством тригеров, я использую простые скрипты генерации xml файлов для импорта. К сожалению, так как в MIB файлах в описании трапов никто не придерживается стандартов, для каждого MIB файла приходится подправлять скрипт генерации xml, и поэтому выкладывать его нет смысла.
Comment